package org.example.ReferenceType;

import java.lang.ref.Reference;
import java.lang.ref.ReferenceQueue;
import java.lang.ref.SoftReference;
import java.util.HashMap;
import java.util.Map;


/**
 * 弱引用案例：
 *               强引用     缓存学生数据            key
 * StudentCache  ------->   HashMap        -----------------------> 学生id
 *                                           value                            软引用
 *                                         --------------------->软引用对象  -------------------> Student
 *
 *
 *
 *
 *
 *
 *
 */
public class StudentCache {
    private static StudentCache cache = new StudentCache();


    public static void main(String[] args) {
        for (int i = 0; ; i++) {
            StudentCache.getInstance().cacheStudent(new Student(i,String.valueOf(i)));
        }
    }
    //缓存学生数据 id  软引用对象->Student
    private Map<Integer,StudentRef> StudentRefs;
    //垃圾Reference的队列
    private ReferenceQueue<Student> q;

    //软引用  --> Student
    private class StudentRef extends SoftReference<Student> {
        private Integer _key = null;
        public StudentRef(Student em, ReferenceQueue<Student> q) {
            // StudentRef --> Student   当内存不足时 引用就断了
            super(em,q);
            _key = em.getId();
        }
    }


    private StudentCache() {
        StudentRefs = new HashMap<Integer,StudentRef>();
        q = new ReferenceQueue<Student>();

    }

    public static StudentCache getInstance() {
        return cache;
    }


    private void cacheStudent(Student em) {
        cleanCache();
        StudentRef ref = new StudentRef(em, q);
        StudentRefs.put(em.getId(),ref);
        System.out.println(StudentRefs.size());
    }
    public Student getStudent(Integer id) {
        Student em = null;
        if (StudentRefs.containsKey(id)) {
            StudentRef ref = StudentRefs.get(id);
            em = ref.get();
        }

        if (em == null) {
            em = new Student(id,String.valueOf(id));
            System.out.println("Reference From StudentInfoCache, ID=" +id);
            this.cacheStudent(em);

        }
        return em;
    }

    private void cleanCache() {
        StudentRef ref = null;
        while ((ref = (StudentRef) q.poll() ) != null) {
            StudentRefs.remove(ref._key);
        }
    }

}
class Student{
    int id;
    String name;


    public Student(int id,String name) {
        this.name = name;
        this.id = id;
    }

    public String getName() {
        return name;
    }

    public void setName(String name) {
        this.name = name;
    }

    public int getId() {
        return id;
    }

    public void setId(int id) {
        this.id = id;
    }
}